package com.bage.finance.biz.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.bage.common.constant.ApiResponseCode;
import com.bage.common.exception.BizException;
import com.bage.common.exception.LoginException;
import com.bage.common.exception.ParameterException;
import com.bage.finance.biz.Enum.SmsCodeTypeEnum;
import com.bage.finance.biz.domain.MemberBindPhone;
import com.bage.finance.biz.dto.form.GetSmsCodeForm;
import com.bage.finance.biz.dto.form.SmsCodeResult;
import com.bage.finance.biz.service.MemberBindPhoneService;
import com.bage.finance.biz.service.MemberLoginService;
import com.bage.finance.biz.constant.RedisKeyConstant;
import com.bage.finance.biz.dto.form.GetBase64CodeForm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 登录服务impl
 *
 * @author Wei
 * @date 2024/07/13
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class MemberLoginServiceImpl implements MemberLoginService {

    final RedisTemplate<String, Object> redisTemplate;

    final MemberBindPhoneService memberBindPhoneService;

    /**
     * 获取客户端id
     * <p>
     * 生成UUID并返回
     *
     * @return {@link String }
     */
    @Override
    public String getClientId() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 获取base64验证码
     *
     * @return {@link String }
     */
    @Override
    public String getBase64Code(GetBase64CodeForm form) {
        // 生成验证码
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(300, 192, 5, 1000);
        String code = lineCaptcha.getCode();
        String imageBase64 = lineCaptcha.getImageBase64();

        log.info("客户端id:{},验证码：{}----", form.getClientId(), code);
        redisTemplate.opsForValue().set(RedisKeyConstant.GRAPHIC_VERIFICATION_CODE + form.getClientId(), code, 15, TimeUnit.MINUTES);
        return imageBase64;
    }

    @Override
    public void sendSmsCode(GetSmsCodeForm form) {
        //    校验图像验证码
        checkBase64Code(form.getClientId(), form.getCode());

        //    拼接redis存储当前手机号key
        String key = RedisKeyConstant.SMS_CODE + form.getSmsCodeType() + form.getPhone();

        //    尝试从Redis中取出对于key的值
        SmsCodeResult tempValue = (SmsCodeResult) redisTemplate.opsForValue().get(key);

        if (tempValue != null) {
            // 判断时间是否超过60s
            long between = DateUtil.between(tempValue.getGetTime(), DateUtil.date(), DateUnit.SECOND);
            if (between < 60) {
                throw new BizException("验证码获取太频繁,请稍后再试");
            }
            //    超过60s 可以将之前的移除
            redisTemplate.delete(key);
        }

        //    判断手机是否注册
        MemberBindPhone memberBindPhone = memberBindPhoneService.getMemberByPhone(form.getPhone());
        if (memberBindPhone == null) {
            //    未注册
            if (form.getSmsCodeType().equals(SmsCodeTypeEnum.LOGIN.getCode())) {
                throw new ParameterException("phone", "手机号未注册");
            }
        } else {
            //    已注册
            if (form.getSmsCodeType().equals(SmsCodeTypeEnum.REG.getCode())) {
                throw new ParameterException("phone", "手机号已被注册");
            }
        }

        //    可以发送短信
        StringBuilder smsCode = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            Integer t = RandomUtil.randomInt(0, 9);
            smsCode.append(t);
        }
        //    调用短信发送服务
        // TODO
        log.info("向手机号:{}发送短信验证码:{}", form.getPhone(), smsCode);

        //    存储到Redis中
        SmsCodeResult value = new SmsCodeResult(smsCode.toString(), DateUtil.date());
        // 过期时间为15分钟
        redisTemplate.opsForValue().set(key, value, 15, TimeUnit.MINUTES);
    }

    /**
     * 检验图形验证码是否有效
     *
     * @param clientId 客户端id
     * @param code     密码
     * @return boolean
     */
    @Override
    public boolean checkBase64Code(String clientId, String code) {

        String key = RedisKeyConstant.GRAPHIC_VERIFICATION_CODE + clientId;
        String resCode = (String) redisTemplate.opsForValue().get(key);
        redisTemplate.delete(key);
        if (!code.equalsIgnoreCase(resCode)) {
            throw new ParameterException("code", "图形验证码错误");
        }
        return true;
    }
}
